﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace DP.RecallDeal.Interface.Requests
{
    public abstract class BaseRequest : IRequest
    {
        public string RequestURL { get; set; }
        public IDictionary<string, string> Params { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }

        public BaseRequest() { }

        public BaseRequest(string userName, string password) 
        {
            this.Username = userName;
            this.Password = password;
            this.Params = new Dictionary<string, string>();
        }

        public BaseRequest(string requestURL, IDictionary<string, string> parameters)
        {
            this.RequestURL = requestURL;
            this.Params = parameters;
        }

        public BaseRequest(string requestURL, IDictionary<string, string> parameters, string userName, string password)
        {
            this.RequestURL = requestURL;
            this.Params = parameters;
            this.Username = userName;
            this.Password = password;
        }

        public virtual string BuildQueryString()
        {
            if (Params == null) return string.Empty;

            string[] parameters = new string[Params.Count];

            int i=0;
            foreach (var item in Params)
            {
                parameters[i] = item.Key + "=" + item.Value;
                i++;
            }

            return string.Join("&", parameters);
        }

        public virtual string BuildURL()
        {
            string queryString = BuildQueryString();
            if (!string.IsNullOrEmpty(queryString))
                return RequestURL + "?" + queryString;

            return RequestURL;
        }        

        public virtual void AddParams(IDictionary<string, string> parameters) 
        {
            //foreach (var item in parameters)
            //{
            //    this.Params[item.Key] = item.Value;
            //}

            foreach (var item in parameters)
            {
                Params.Add(item);
            }
        }

        public virtual Stream GetResponseStreamByGET()
        {
            string url = BuildURL();

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Credentials = new NetworkCredential(Username, Password);
            request.PreAuthenticate = true;

            string authorizationHeader = Username + ":" + Password;
            request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(authorizationHeader)));

            request.Method = WebRequestMethods.Http.Get;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            Stream resStream = response.GetResponseStream();
            return resStream;
        }

        public virtual Stream GetResponseStreamByPOST()
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            Stream responseStream = null;

            try
            {
                string url = RequestURL;

                request = (HttpWebRequest)WebRequest.Create(url);

                CredentialCache myCache = new CredentialCache();
                myCache.Add(new Uri(url), "Basic", new NetworkCredential(Username, Password));
                request.Credentials = myCache;

                string authorizationHeader = Username + ":" + Password;
                request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(authorizationHeader)));

                request.Method = WebRequestMethods.Http.Post;

                string queryString = BuildQueryString();

                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = queryString.Length;

                StreamWriter sw = new StreamWriter(request.GetRequestStream());
                sw.Write(queryString);
                sw.Flush();
                sw.Close();

                response = (HttpWebResponse)request.GetResponse();

                responseStream = response.GetResponseStream();
                return responseStream;
            }
            catch (System.Net.WebException webEx)
            {
                if (webEx.Response != null)
                {
                    Stream exStream = webEx.Response.GetResponseStream();

                    StreamReader reader = new StreamReader(exStream);
                    string error = reader.ReadToEnd();
                    //TODO: Log error
                }
            }
            catch (Exception ex)
            {
                //TODO: Log error
            }
            return null;
        }

        public virtual string GetResponseDataByPOST()
        {
            Stream stream = GetResponseStreamByPOST();
            return GetResponseData(stream);
        }

        public virtual string GetResponseDataByGET()
        {
            Stream stream = GetResponseStreamByGET();
            return GetResponseData(stream);
        }

        private string GetResponseData(Stream stream)
        {
            string data = (new StreamReader(stream)).ReadToEnd();

            return data;
        }
    }
}
